<!DOCTYPE html>
<html lang="en">
<head>
	<meta http-equiv="Content-type" content="text/html; charset=utf-8">
	<title>dijit.Tree / dijit.tree.ObjectStoreModel automated test</title>

	<script type="text/javascript" src="../boilerplate.js"></script>

	<script type="text/javascript">
		require([
			"doh/runner",
			"dojo/_base/array",
			"dojo/aspect",
			"dojo/cookie",
			"dojo/dom-class",
			"dojo/_base/lang",
			"dojo/on",
			"dojo/_base/window",
			"dojo/store/Memory",
			"dojo/store/Observable",
			"dijit/registry",
			"dijit/Tree",
			"dijit/tree/ObjectStoreModel",
			"dijit/tree/dndSource",
			"dijit/tests/_data/geography",
			"dijit/tests/helpers",	// functions to help test
			"dojo/domReady!"
		], function(doh, array, aspect, cookie, domClass, lang, on, win, Memory, Observable,
					registry, Tree, ObjectStoreModel, dndSource, data, helpers){

			var myStore, myModel, myTree, myTree2;

			// TreeNodes
			var world, europe, asia, africa, kenya;

			// Function to create / reset the data store and model
			function setup(){
				// Create test store.
				myStore = new Memory({
					data: data
				});

				// Since dojo.store.Memory doesn't have various store methods we need, we have to add them manually
				myStore.getChildren = function(object){
					// Add a getChildren() method to store for the data model where
					// children objects point to their parent (aka relational model)
					return this.query({parent: this.getIdentity(object)});
				};

				aspect.around(myStore, "put", function(originalPut){
					// To support DnD, the store must support put(child, {parent: parent}).
					// Since our store is relational, that just amounts to setting child.parent
					// to the parent"s id.
					return function(obj, options){
						if(options && options.parent){
							obj.parent = options.parent.id;
						}
						return originalPut.call(myStore, obj, options);
					}
				});

				// Wrap the store in Observable so that updates to the store are reflected
				myStore = new Observable(myStore);
				doh.t(myStore, "store created");

				// Create the model
				myModel = new ObjectStoreModel({store: myStore, query: {id: "earth"}});
				doh.t(myModel, "model created");
			}

			doh.register("setup", setup);

			doh.register("basic", [
				{
					name: "create",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						myTree = new Tree({
							id: "myTree",
							model: myModel,
							persist: false,		// persist==true is too hard to test
							dndController: dndSource
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();

						world = myTree.rootNode;

						// Give the tree time to load, and the do checks that it
						// loaded correctly
						setTimeout(d.getTestCallback(function(){
							doh.t(world, "root node exists");
							doh.is("The earth", world.label, "world node label");
							doh.t(world.isExpanded, "root node is expanded");

							var children = world.getChildren();
							doh.is(6, children.length, "six children");
							doh.is("Africa", children[0].label, "first child");
							doh.f(children[0].isExpanded, "first child not expanded");
							doh.is("South America", children[5].label, "last child");

							// Last child has special CSS for drawing the grid lines
							doh.f(domClass.contains(children[3].domNode, "dijitTreeIsLast"), "middle node doesn't have dijitTreeIsLast");
							doh.t(domClass.contains(children[5].domNode, "dijitTreeIsLast"), "last node has dijitTreeIsLast");
						}), 750);
						return d;
					}
				},

				function openEurope(){
					var d = new doh.Deferred();

					europe = world.getChildren()[3];
					doh.is("Europe", europe.label, "europe node label");
					doh.t(europe, "europe node exists");

					// Click on Europe to open it
					on.emit(europe.expandoNode, "click", {bubbles: true});

					// Give the children time to load, and the do checks that they
					// loaded correctly
					setTimeout(d.getTestCallback(function(){
						doh.t(europe.isExpanded, "europe node is expanded");

						var children = europe.getChildren();
						doh.is(4, children.length, "children count");
						doh.is("Germany", children[0].label, "first child");
						doh.f(children[0].isExpanded, "first child not expanded");
						doh.is("Italy", children[3].label, "last child");

						// Last child has special CSS for drawing the grid lines
						doh.f(domClass.contains(children[1].domNode, "dijitTreeIsLast"), "middle node doesn't have dijitTreeIsLast");
						doh.t(domClass.contains(children[3].domNode, "dijitTreeIsLast"), "last node has dijitTreeIsLast");
					}), 750);
					return d;
				},

				function openAsia(){
					var d = new doh.Deferred();

					asia = world.getChildren()[1];
					doh.is("Asia", asia.label, "asia node label");
					doh.t(asia, "europe node exists");

					// Click on Europe to open it
					on.emit(asia.expandoNode, "click", {bubbles: true});

					// Give the children time to load, and the do checks that they
					// loaded correctly
					setTimeout(d.getTestCallback(function(){
						doh.t(asia.isExpanded, "asia node is expanded");

						var children = asia.getChildren();
						doh.is(4, children.length, "children count");
						doh.is("China", children[0].label, "first child");
						doh.is("Mongolia", children[3].label, "last child");
					}), 750);
					return d;
				}
			]);

			doh.register("data store binding", [
				function itemUpdate(){
					// Test that Tree noticed when data store items change, and updates accordingly

					myStore.put({ id: "ES", name:"España", type:"country", parent: "EU" });
					doh.is("España", innerText(europe.getChildren()[2].labelNode), "label changed");
				},

				function topLevelItemDelete(){
					// Delete a top level item.

					// Remove "South America"
					myStore.remove("SA");

					var children = world.getChildren();
					doh.is(5, children.length, "five children");
					doh.is("North America", children[4].label, "last child");
					doh.t(domClass.contains(children[4].domNode, "dijitTreeIsLast"),
							"North america has become the last node so it gets the CSS class for that");
				},

				function nestedItemDelete(){
					// Delete a nested item

					// Remove "China"
					myStore.remove("CN");

					var children = asia.getChildren();
					doh.is(3, children.length, "three children");
				},

				function topLevelItemInsert(){
					// Create a new top level item as last child.
					// ForestStoreModel needs to realize that the top level children have changed and notify Tree.

					myStore.add({
						id: "PA",
						name:"Pacifica",
						type:"continent",
						parent: "earth"
					});

					var children = world.getChildren();
					doh.is(6, children.length, "six children");
					doh.is("Pacifica", children[5].label, "last child");
					doh.f(domClass.contains(children[4].domNode, "dijitTreeIsLast"),
						"North America no longer last child");
					doh.t(domClass.contains(children[5].domNode, "dijitTreeIsLast"),
						"Pacifica is last child");
				},

				function topLevelItemModify(){
					// Modify a top level item so it's no longer top level.

					myStore.put({
						id: "PA",
						name:"Pacifica",
						type:"continent",
						parent: "AS"
					});

					doh.is(5, world.getChildren().length, "world children");
					doh.is(4, asia.getChildren().length, "asia children");
				},

				function nestedItemModify(){
					// Modify a nested item so it matches the query for top level items in the tree.

					myStore.put({
						id: "PA",
						name:"Pacifica",
						type:"continent",
						parent: "earth"
					});

					doh.is(6, world.getChildren().length, "world children");
					doh.is(3, asia.getChildren().length, "asia children");
				}
			]);

			doh.register("DnD", [
				// Drag Germany from Europe to Asia
				function dragGermanyToAsia(){
					var asiaItem = myStore.get("AS"),
						europeItem = myStore.get("EU"),
						germanyItem = myStore.get("DE");
					myModel.pasteItem(germanyItem, europeItem, asiaItem);
					doh.is(3, europe.getChildren().length, "europe children");
					doh.is(4, asia.getChildren().length, "asia children");
					doh.is("Germany", asia.getChildren()[3].label, "last child of asia");
				},

				// Drag Germany from Asia to Europe
				function dragGermanyToEurope(){
					var asiaItem = myStore.get("AS"),
						europeItem = myStore.get("EU"),
						germanyItem = myStore.get("DE");
					myModel.pasteItem(germanyItem, asiaItem, europeItem);
					doh.is(3, asia.getChildren().length, "asia children");
					doh.is(4, europe.getChildren().length, "europe children");
					doh.is("Germany", europe.getChildren()[3].label, "last child of europe");
				},

				function openAfrica(){
					var d = new doh.Deferred();

					africa = world.getChildren()[0];
					doh.is("Africa", africa.label, "africa node label");
					doh.t(africa, "africa node exists");

					// Click on Africa to open it
					on.emit(africa.expandoNode, "click", {bubbles: true});

					// Give the children time to load, and the do checks that they
					// loaded correctly
					setTimeout(d.getTestCallback(function(){
						doh.t(africa.isExpanded, "node is expanded");

						var children = africa.getChildren();
						doh.is(3, children.length, "children count");
					}), 750);
					return d;
				},

				function openKenya(){
					var d = new doh.Deferred();

					kenya = africa.getChildren()[1];
					doh.t(kenya, "kenya node exists");
					doh.is("Kenya", kenya.label, "kenya node label");

					// Click on Kenya to open it
					on.emit(kenya.expandoNode, "click", {bubbles: true});

					// Give the children time to load, and the do checks that they
					// loaded correctly
					setTimeout(d.getTestCallback(function(){
						doh.t(kenya.isExpanded, "node is expanded");

						var children = kenya.getChildren();
						doh.is(2, children.length, "children count");
					}), 750);
					return d;
				},

				// Dragging open node to make sure it stays open.
				function dragKenyaToAsia(){
					var asiaItem = myStore.get("AS"),
						africaItem = myStore.get("AF"),
						kenyaItem = myStore.get("KE");
					myModel.pasteItem(kenyaItem, africaItem, asiaItem);
					doh.is(4, asia.getChildren().length, "asia children");
					doh.is("Kenya", asia.getChildren()[3].label, "last child of asia");
					doh.is(kenya, asia.getChildren()[3], "same TreeNode as before");
					doh.t(kenya.isExpanded, "node is still expanded");
					doh.is(2, kenya.getChildren().length, "same children count as before");
				},

				// Put Kenya back in Africa
				function dragKenyaToAfrica(){
					var asiaItem = myStore.get("AS"),
						africaItem = myStore.get("AF"),
						kenyaItem = myStore.get("KE");
					myModel.pasteItem(kenyaItem, asiaItem, africaItem);
					doh.is(3, asia.getChildren().length, "asia children");
					doh.is(3, africa.getChildren().length, "africa children");
				}

			]);

			doh.register("paths", [
				function getPath(){
					var france = europe.getChildren()[0];

					// Select the node.   can't emit "click" because dndSelector listens for mousedown & mouseup.
					// And before the mousedown, we need a mouseover event, so _dndContainer.js sets this.current.
					on.emit(france.labelNode, navigator.msPointerEnabled ? "MSPointerOver" : "mouseover", {bubbles: true});
					on.emit(france.labelNode, navigator.msPointerEnabled ? "MSPointerDown" : "mousedown", {button: dojo.mouseButtons.LEFT, bubbles: true});
					on.emit(france.labelNode, navigator.msPointerEnabled ? "MSPointerUp" : "mouseup", {button: dojo.mouseButtons.LEFT, bubbles: true});

					var path = myTree.get("path");
					doh.is("earth, EU, FR",
							array.map(myTree.get("path"), function(obj){ return obj.id; }).join(", "),
							"serialized path");
				},
				{
					name: "createWithPath",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();
						myTree2 = new Tree({
							id: "myTree2",
							model: myModel,
							persist: false,		// persist==true is too hard to test
							dndController: dndSource,
							path: ["earth", "EU", "IT"]
						}).placeAt(win.body());
						doh.t(myTree2, "myTree2 created");

						myTree2.startup();

						setTimeout(d.getTestCallback(function(){
							doh.t(myTree2.rootNode, "root node exists");
							doh.t(myTree2.rootNode.isExpanded, "root node is expanded");
							doh.t(myTree2.rootNode.getChildren()[3].isExpanded, "europe node is expanded");
							doh.is("Italy", myTree2.selectedNode.label, "selected correct node");
						}), 2000);

						return d;
					}
				},
				function copyPath(){
					var d = new doh.Deferred();

					myTree.set("path", myTree2.get("path")).then(d.getTestCallback(function(items){
						doh.is("earth, EU, IT", array.map(items, function(item){ return item.id; }).join(", "));
						doh.t(world.isExpanded, "root node is expanded");
						doh.t(world.getChildren()[3].isExpanded, "europe node is expanded");
						doh.is("Italy", myTree.get("selectedNode").label, "selected correct node");
					}));

					return d;
				},

				{
					name: "copyPathByIds",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						myTree.set("path", ["earth", "NA", "CA", "Ottawa"]).then(d.getTestErrback(function(){
							var path = array.map(myTree.get("path"), function(item){ return item.id; });
							doh.is(["earth", "NA", "CA", "Ottawa"], path, "path got set on myTree");

							myTree2.set("path", path).then(d.getTestCallback(function(){
								doh.t(myTree2.rootNode.isExpanded, "root node is expanded");
								doh.t(myTree2.rootNode.getChildren()[4].isExpanded, "north america node is expanded");
								doh.t(myTree2.rootNode.getChildren()[4].getChildren()[1].isExpanded, "canada node is expanded");
								doh.is("Ottawa", myTree2.get("selectedNode").label, "selected correct node");
							}));
						}));

						return d;
					}
				},

				function setPathToNull(){
					var d = new doh.Deferred();

					myTree2.set("path", []).then(d.getTestCallback(function(){
						doh.is(null, myTree2.get("selectedNode"), "no selected node");
					}));
					return d;
				},

				function setPathToRoot(){
					var d = new doh.Deferred();

					myTree2.set("path", ["earth"]).then(d.getTestCallback(function(){
						doh.is(myTree2.rootNode, myTree2.get("selectedNode"), "selected root node");
					}));
					return d;
				},

				function setPaths(){
					var d = new doh.Deferred();

					myTree2.set("paths", [["earth", "AF", "KE", "Nairobi"],
										["earth", "NA", "MX", "Guadalajara"]]).then(d.getTestCallback(function(paths){
						doh.is("earth, AF, KE, Nairobi", array.map(paths[0], function(item){ return item.id; }).join(", "));
						doh.is("earth, NA, MX, Guadalajara", array.map(paths[1], function(item){ return item.id; }).join(", "));
						var ids = array.map(myTree2.selectedItems, function(x){return myTree2.model.getIdentity(x);}).sort();
						doh.is(["Guadalajara", "Nairobi"], ids);
					}));
					return d;
				},
				function setEmptyPath(){
					var d = new doh.Deferred();

					// setting an empty path is interpreted as selecting nothing
					myTree2.set("path", []).then(
						d.getTestCallback(function(){
							doh.is(0, myTree2.get("selectedNodes").length, "no nodes selected");
						}),
						d.getTestCallback(function(e){
							throw e;
						})
					);

					return d;
				},
				function setInvalidPath(){
					var d = new doh.Deferred();
					myTree2.set("path", ["earth", "AF", "KE", "Narnia"]).then(
						function(){
							d.errback("Should have gotten error trying to set invalid path");
						},
						d.getTestCallback(function(e){
							doh.t(e instanceof Tree.PathError, "got PathError");
						})
					);

					return d;
				}

			]);

			doh.register("destroy", [
				function destroyTree(){
					// Just running this to make sure we don"t get an exception
					myTree.destroy();
					myTree2.destroy();
				}
			]);

			doh.register("delete selected node", [
				{
					name: "create",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						myTree = new Tree({
							id: "myTree",
							model: myModel,
							persist: false,		// persist==true is too hard to test
							path: ["earth", "EU", "IT"]
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();

						myTree.onLoadDeferred.then(d.getTestCallback(function(){
							doh.is("IT", myTree.get("selectedItem").id);
						}));

						return d;
					}
				},

				function deleteSelectedItem(){
					myStore.remove("IT");
				},

				function selectNewItem(){
					// Since EU is already open this set("path", ...) should execute immediately
					myTree.set("path", ["earth", "EU", "FR"]);
					doh.is("FR", myTree.get("selectedItem").id);
				}
			]);


			doh.register("nobidi", [
				// Make sure that Tree doesn't have spurious lang="" dir="" on nodes
				function noLangDir(){
					doh.t(myTree.rootNode, "root node exists");
					doh.t(myTree.rootNode.isExpanded, "root node is expanded");
					doh.f(domClass.contains(myTree.rootNode, "lang"), "no (empty) lang attribute on root TreeNode");
					doh.f(domClass.contains(myTree.rootNode, "dir"), "no (empty) dir attribute on root TreeNode");

					var children = myTree.rootNode.getChildren();
					doh.f(domClass.contains(children[2], "lang"), "no (empty) lang attribute on child TreeNode");
					doh.f(domClass.contains(children[2], "dir"), "no (empty) dir attribute on child TreeNode");
				}
			]);

			doh.register("expand/contract", [
				{
					name: "initiallyExpanded",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						myTree = new Tree({
							id: "myTreeExpand",
							model: myModel,
							persist: false,		// persist==true is too hard to test
							autoExpand: true
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();

						world = myTree.rootNode;

						myTree.onLoadDeferred.then(d.getTestCallback(function(){
							doh.t(world, "root node exists");
							doh.t(world.isExpanded, "root node is expanded");

							var children = world.getChildren();
							doh.is(6, children.length, "world children");
							doh.t(children[0].isExpanded, "Africa expanded");
							doh.t(children[0].getChildren()[2].isExpanded, "Kenya expanded too");
							doh.is(2, children[0].getChildren()[2].getChildren().length, "Kenya children");
							doh.t(children[4].isExpanded, "North America expanded");
							doh.is(3, children[4].getChildren().length, "North America children");
						}));

						return d;
					}
				},
				{
					name: "collapseAll",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						myTree.collapseAll().then(d.getTestCallback(function(){
							doh.t(world, "root node exists");
							doh.f(world.isExpanded, "root node collapsed");

							var children = world.getChildren();
							doh.is(6, children.length, "world children");
							doh.f(children[0].isExpanded, "Africa collapsed");
							doh.f(children[0].getChildren()[2].iscollapsed, "Kenya collapsed too");
							doh.is(2, children[0].getChildren()[2].getChildren().length, "Kenya children");
							doh.f(children[4].isExpanded, "North America collapsed");
							doh.is(3, children[4].getChildren().length, "North America children");
						}));

						return d;
					}
				},
				{
					name: "expandAll",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						myTree.destroy();

						myTree = new Tree({
							id: "myTreeExpand",
							model: myModel,
							persist: false,		// persist==true is too hard to test
							autoExpand: false
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();

						world = myTree.rootNode;

						myTree.onLoadDeferred.then(d.getTestErrback(function(){
							doh.t(world, "root node exists");
							doh.t(world.isExpanded, "root node is expanded");

							var children = world.getChildren();
							doh.is(6, children.length, "world children");
							doh.f(children[0].isExpanded, "Africa collapsed");

							myTree.expandAll().then(d.getTestCallback(function(){
								var children = world.getChildren();
								doh.t(children[0].isExpanded, "Africa expanded");
								doh.t(children[0].getChildren()[2].isExpanded, "Kenya expanded too");
								doh.t(children[4].isExpanded, "North America expanded");
								doh.is(3, children[4].getChildren().length, "North America children");
							}));
						}));

						return d;
					}
				},
				{
					name: "collapseShowRootFalseTree",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						myTree.destroy();

						myTree = new Tree({
							id: "myTreeExpand",
							model: myModel,
							persist: false,		// persist==true is too hard to test
							showRoot: false
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();

						world = myTree.rootNode;

						myTree.onLoadDeferred.then(d.getTestErrback(function(){
							myTree._expandNode(myTree.rootNode.getChildren()[0]).then(d.getTestErrback(function(){
								var children = world.getChildren();
								doh.t(children[0].isExpanded, "Africa collapsed");

								myTree.collapseAll().then(d.getTestCallback(function(){
									doh.t(world, "root node exists");
									doh.t(world.isExpanded, "root node expanded (because it's hidden");

									doh.f(children[0].isExpanded, "Africa collapsed");
									doh.t(helpers.isVisible(children[0]), "Africa node visible");
								}));
							}));
						}));

						return d;
					}
				}
			]);

			doh.register("persistence", [
				// Reset the data to original values
				setup,

				{
					name: "create",
					timeout: 5000,
					runTest: function(){
						if(registry.byId("myTree")){
							registry.byId("myTree").destroy();
						}
						cookie("myTreeSaveStateCookie", "");

						myTree = new Tree({
							id: "myTree",
							model: myModel,
							persist: true
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();

						world = myTree.rootNode;

						return myTree.onLoadDeferred;
					}
				},

				{
					name: "expand and contract",
					timeout: 5000,
					runTest: function(){

						var d = new doh.Deferred();

						na = world.getChildren()[4];
						doh.is("North America", na.label, "North America node label");

						// Click on North America to open it
						on.emit(na.expandoNode, "click", {bubbles: true});

						// Wait for animation to complete
						setTimeout(d.getTestErrback(function(){
							mx = na.getChildren()[0];
							doh.is("Mexico", mx.label, "Mexico node label");

							// Click on Mexico to open it
							on.emit(mx.expandoNode, "click", {bubbles: true});

							// Wait for animation to complete.
							setTimeout(d.getTestErrback(function(){
								// Click on North America again, to close it
								on.emit(na.expandoNode, "click", {bubbles: true});
								setTimeout(d.getTestCallback(function(){
									// Wait for close animation to finish and then return success
								}), 500);
							}), 500);
						}), 500);

						return d;
					}
				},

				{
					name: "recreate tree",
					timeout: 5000,
					runTest: function(){
						myTree.destroy();

						myTree = new Tree({
							id: "myTree",
							model: myModel,
							persist: true
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();

						world = myTree.rootNode;

						return myTree.onLoadDeferred;
					}
				},

				{
					name: "check tree state",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();

						na = world.getChildren()[4];
						doh.is("North America", na.label, "North America node label");

						doh.f(na.isExpanded, "North America collapsed");

						// Click on North America to open it
						on.emit(na.expandoNode, "click", {bubbles: true});

						setTimeout(d.getTestCallback(function(){
							doh.t(na.isExpanded, "North America expanded");
							mx = na.getChildren()[0];
							doh.is("Mexico", mx.label, "Mexico node label");
							doh.t(mx.isExpanded, "Mexico expanded");
						}), 500);

						return d;
					}
				}
			]);

			// Tests that TreeNodes that are destroyed don't linger in selection, etc.
			doh.register("destroyed nodes", [
				// Reset the data to original values
				setup,

				{
					name: "create",
					timeout: 5000,
					runTest: function(){
						cookie("myDeleteTreeSaveStateCookie", "");
						myTree = new Tree({
							id: "myDeleteTree",
							model: myModel,
							persist: true
						}).placeAt(win.body());
						doh.t(myTree, "tree created");

						myTree.startup();
						doh.is("earth", cookie("myDeleteTreeSaveStateCookie"), "initial persistence cookie just earth");
					}
				},

				function removedFromSelection(){
					var d = new doh.Deferred();
					// Select Mexico city
					myTree.set("path", ["earth", "NA", "MX", "Mexico City"]).then(d.getTestErrback(function(){
						doh.is(1, myTree.get("paths").length, "one selected node");
						var selectedNode = myTree.get("selectedNode");

						// Ancestors of the selected node should be expanded, and that should be saved
						// in the cookie
						doh.is("earth,earth/NA,earth/NA/MX", cookie("myDeleteTreeSaveStateCookie"),
								"Earth, North America, Mexico should be listed as expanded");

						// Remove selection's ancestor
						myStore.remove("NA");

						// use setTimeout() to give Tree time to realize this isn't a drag & drop, but that
						// the North America subtree was truly deleted
						setTimeout(d.getTestCallback(function(){
							doh.t(selectedNode._destroyed, "the selected node was destroyed (along with it's ancestor)");
							doh.is(0, myTree.get("paths").length, "no selected nodes");
							doh.is("earth", cookie("myDeleteTreeSaveStateCookie"),
									"North America and Mexico should have been removed from list of expanded nodes")
						}), 10)
					}));
					return d;
				},

				{
					name: "reinsert deleted descendants",
					timeout: 5000,
					runTest: function(){
						var d = new doh.Deferred();
						myStore.put({ id: "NA", name:"North America", type:"continent", parent: "earth" });
						myStore.put({ id: "MX", name:"Mexico", type:"country",  population:"108 million", area:"1,972,550 sq km",
								parent: "NA" });
						myStore.put({ id: "Mexico City", name:"Mexico City", type:"city", population:"19 million", timezone:"-6 UTC", parent: "MX"});
						myStore.put({ id: "Guadalajara", name:"Guadalajara", type:"city", population:"4 million", timezone:"-6 UTC", parent: "MX" });

						myTree.set("path", ["earth", "NA", "MX", "Mexico City"]).then(
							d.getTestCallback(function(){
								var node = myTree.get("selectedNode");
								doh.isNot(null, node, "got a selected node");
								doh.f(node._destroyed, "not destroyed");
								doh.f(node.getParent()._destroyed, "parent not destroyed");
								doh.f(node.getParent().getParent()._destroyed, "grandparent not destroyed");
							}),
							d.getTestErrback(function(err){
								throw err;
							})
						);

						return d;
					}
				}
			]);

			doh.register("HTML tree", {
				name: "create",
				timeout: 5000,
				runTest: function(){
					var d = new doh.Deferred();

					// Create test store.
					htmlData = array.map(data, function(o){
						var n = lang.clone(o);
						n.name = "<i>" + o.name + "</i>";
						return n;
					});
					htmlStore = new Memory({
						data: htmlData
					});

					// Since dojo.store.Memory doesn't have various store methods we need, we have to add them manually
					htmlStore.getChildren = function(object){
						// Add a getChildren() method to store for the data model where
						// children objects point to their parent (aka relational model)
						return this.query({parent: this.getIdentity(object)});
					};

					// Create the model
					htmlModel = new ObjectStoreModel({
						store: htmlStore,
						labelType: "html",
						query: {id: "earth"}
					});
					doh.t(htmlModel, "model created");

					htmlTree = new Tree({
						id: "htmlTree",
						model: htmlModel
					}).placeAt(win.body());
					doh.t(htmlTree, "tree created");

					htmlTree.startup();

					world = htmlTree.rootNode;

					return htmlTree.expandAll().then(function(){
						doh.t(world, "root node exists");
						doh.is("<i>The earth</i>", world.label, "world node label");
						doh.is("<i>the earth</i>", world.labelNode.innerHTML.toLowerCase(), "world node labelNode.innerHTML");

						var children = world.getChildren();
						doh.is("<i>Africa</i>", children[0].label, "first child");
						doh.is("<i>africa</i>", children[0].labelNode.innerHTML.toLowerCase(), "first child labelNode.innerHTML");
					});
				}
			});

			doh.register("plain text tree", {
				name: "create",
				timeout: 5000,
				runTest: function(){
					var d = new doh.Deferred();

					// Create test store.
					plainTextData = array.map(data, function(o){
						var n = lang.clone(o);
						n.name = "<>&" + o.name;
						return n;
					});
					plainTextStore = new Memory({
						data: plainTextData
					});

					// Since dojo.store.Memory doesn't have various store methods we need, we have to add them manually
					plainTextStore.getChildren = function(object){
						// Add a getChildren() method to store for the data model where
						// children objects point to their parent (aka relational model)
						return this.query({parent: this.getIdentity(object)});
					};

					// Create the model
					plainTextModel = new ObjectStoreModel({
						store: plainTextStore,
						labelType: "text",
						query: {id: "earth"}
					});
					doh.t(plainTextModel, "model created");

					plainTextTree = new Tree({
						id: "plainTextTree",
						model: plainTextModel
					}).placeAt(win.body());
					doh.t(plainTextTree, "tree created");

					plainTextTree.startup();

					world = plainTextTree.rootNode;

					return plainTextTree.expandAll().then(function(){
						doh.t(world, "root node exists");
						doh.is("<>&The earth", world.label, "world node label");
						doh.is("<>&The earth", helpers.innerText(world.labelNode), "world node labelNode.innerText");

						var children = world.getChildren();
						doh.is("<>&Africa", helpers.innerText(children[0].labelNode), "first child");
					});
				}
			});

			doh.run();

 		});
	</script>

</head>
<body class="claro" role="main">

	<h1 class="testTitle">Tree using Tree.ObjectStore (against dojo.store) Automated Test</h1>

</body>
</html>
